
import { ArrayMethods } from './arr'
import Dep from './dep'
export function observer(data) {
  //1判断
  if (typeof data !== 'object' || data === null) {
    return;
  }
  //1 对象通关一个类
  return new Observer(data);
}


class Observer {
  constructor(data) {

    // 给data定义一个属性，对所有的值添加了一个__ob__属性
    Object.defineProperty(data, '__ob__', {
      value: this, //this 指向observer实例
      enumerable: false
    })


    //判断数据是数组还是对象
    if (Array.isArray(data)) {
      data.__proto__ = ArrayMethods;
      //如果是数组对象
      this.observeArray(data)
    }
    else {
      this.walk(data); //遍历对象
    }
  }
  walk(data) {
    Object.keys(data).forEach(key => {
      defineReactive(data, key, data[key]);
    })
  }
  observeArray(value) {//[{a:1}]
    for (let i = 0; i < value.length; i++) {
      observer(value[i])
    }
  }
}

function defineReactive(data, key, value) {

  observer(value)
  let dep = new Dep(); //给data每一个属性添加了一个dep
  Object.defineProperty(data, key, {
    enumerable: true,  //表示能否通过for in循环访问属性，默认值为false
    configurable: true, //是否可再次修改配置，项默认值是false
    get() {
      //收集watcher
      if(Dep.target){
        dep.depend()
      }
      console.log(dep);
      return value; //读取时内部调用的函数，默认值是undefined
    },
    set(newValue) { // 写入时内部调用的函数，默认值是undefined
      if (newValue === value) return value;
      observer(newValue)
      value = newValue;
      dep.notify() //跟新视图
    }
  })
}


//总结
/**
 * 1、Object.defineProperty,有缺点，只能对对象中的一个属性进行劫持
 * 2、遍历
 * 3、递归
 **/


//数组，函数劫持，重写方法
/**
 * 1、Object.create(Array.prototype) 创建一个新对象，新对象原型是数组Array的原型
 */
